package static_data

import (
	"fmt"
	"os"
	"strings"

	"github.com/tealeg/xlsx"

	"nggs/tools/print"
)

const (
	enumSheetSuffix = "@枚举"
)

func ReadEnum(path string) (allEnum []*Enum, err error) {
	xf, err := xlsx.OpenFile(path)
	if err != nil {
		return
	}

	allEnum = []*Enum{}

	for _, sheet := range xf.Sheets {
		if !strings.HasSuffix(sheet.Name, enumSheetSuffix) {
			print.Debugf("分页[%s]不是枚举分页", sheet.Name)
			continue
		}
		es, e := readEnumSheet(sheet)
		if e != nil {
			err = e
			return
		}
		allEnum = append(allEnum, es...)
	}

	return
}

const (
	enumBeginRow = 1

	enumNameCol         = 0
	enumCommentCol      = 1
	enumValueNameCol    = 2
	enumValueCol        = 3
	enumValueAliasCol   = 4
	enumValueCommentCol = 5
)

func readEnumSheet(sheet *xlsx.Sheet) (es []*Enum, err error) {
	for row := enumBeginRow; row < sheet.MaxRow; row++ {
		name := strings.TrimSpace(sheet.Cell(row, enumNameCol).Value)
		comment := strings.TrimSpace(sheet.Cell(row, enumCommentCol).Value)
		valueName := strings.TrimSpace(sheet.Cell(row, enumValueNameCol).Value)
		value := strings.TrimSpace(sheet.Cell(row, enumValueCol).Value)
		valueAlias := strings.TrimSpace(sheet.Cell(row, enumValueAliasCol).Value)
		valueComment := strings.TrimSpace(sheet.Cell(row, enumValueCommentCol).Value)

		if name == "" {
			continue
		}
		name = strings.Title(name)
		e := GetEnumByName(es, name)
		if e == nil {
			if comment == "" {
				print.Errorf("第[%d]行的枚举注释为空，无法新增枚举", row+1)
				continue
			}
			if valueName == "" {
				print.Errorf("第[%d]行的枚举值名为空，无法新增枚举", row+1)
				continue
			}
			if value == "" {
				print.Errorf("第[%d]行的枚举值为空，无法新增枚举", row+1)
				continue
			}
			e = NewEnum(name, comment)
			es = append(es, e)
		}
		if valueName == "" {
			print.Errorf("第[%d]行的枚举值名为空，无法新增枚举值", row+1)
			continue
		}
		if value == "" {
			print.Errorf("第[%d]行的枚举值为空，无法新增枚举值", row+1)
			continue
		}
		v := NewEnumValue(valueName, value, valueAlias, valueComment)
		E := v.Format()
		if E != nil {
			print.Errorf("格式化第[%d]行的枚举值失败，%s", row+1, E)
			continue
		}
		E = e.AppendValue(v)
		if E != nil {
			print.Errorf("添加第[%d]行的枚举值失败，%s", row+1, E)
			continue
		}
	}
	for _, e := range es {
		E := e.Format()
		if E != nil {
			print.Errorf("格式化枚举[%s]失败，%s", e.Name, E)
			continue
		}
	}
	return
}

func ReadType(path string) (err error) {
	return
}

func Read(path string, tableTags []string, attributeTags []string, dataTags []string, readData bool, sd *StaticData, clientMode bool) (e *Excel, err error) {
	info, err := os.Lstat(path)
	if err != nil {
		return
	}

	xf, err := xlsx.OpenFile(path)
	if err != nil {
		return
	}

	name := strings.TrimSuffix(info.Name(), ".xlsx")

	e = NewExcel(name)

	var s *Sheet
	for _, sheet := range xf.Sheets {
		s, err = readSheet(name, sheet, tableTags, attributeTags, dataTags, readData, sd, clientMode)
		if err != nil {
			return
		}
		if s == nil {
			return
		}
		//if len(s.xlsxFields) == 0 {
		//	err = &ErrTableFieldEmpty{}
		//	return
		//}
		err = e.Append(s)
		if err != nil {
			return
		}
		err = sd.AppendTable(s)
		if err != nil {
			return
		}
	}

	return
}

var (
	MaxRow = 10000
	MaxCol = 150
)

func isInList(v string, list []string) bool {
	for _, i := range list {
		if v == i {
			return true
		}
	}
	return false
}

func readSheet(staticDataName string, sheet *xlsx.Sheet, tableTags []string, attributeTags []string, dataTags []string, readData bool, g *StaticData, clientMode bool) (s *Sheet, err error) {
	s = NewSheet(sheet.Name)

	var row int
	var column int
	var isComment bool

	var maxRow = MaxRow
	if maxRow > sheet.MaxRow {
		maxRow = sheet.MaxRow
	}
	var maxCol = MaxCol
	if maxCol > sheet.MaxCol {
		maxCol = sheet.MaxCol
	}

	// 先定位tag，确定是不是配置表
scanTagLoop:
	for row < maxRow {
		isComment, err = CanIgnoreSheetRow(sheet, row)
		if err != nil && err.Error() != "cell value is empty" {
			print.Panicf("[%s] 扫描tag失败, %s", staticDataName, err)
		}
		if isComment {
			row++
			continue
		}
		column = 0
		for column < maxCol {
			cell := sheet.Cell(row, column)
			if cell == nil {
				print.Panicf("分页[%s]的单元格[%d,%d]是nil", sheet.Name, row, column)
				continue
			}
			if cell.Value == "" || cell.Value[0] == '#' {
				column++
				continue
			}
			if s.TableNameOffset == nil && isInList(cell.Value, tableTags) {
				s.TableNameOffset = NewOffset(row, column+1)
				nameCell := sheet.Cell(s.TableNameOffset.Row(), s.TableNameOffset.Column())
				if nameCell == nil {
					print.Panicf("分页[%s]名字单元格%+v是nil", sheet.Name, s.TableNameOffset)
					continue
				}
				if nameCell.Value == "" {
					print.Debugf("分页[%s]%+v表名为空", sheet.Name, s.TableNameOffset)
					return nil, nil
				}
				if nameCell.Value[0] == '#' {
					print.Debugf("分页[%s]%+v表名被注释了", sheet.Name, s.TableNameOffset)
					err = nil
					return nil, nil
				}
				s.Name = nameCell.Value
				commentCell := sheet.Cell(s.TableNameOffset.Row(), s.TableNameOffset.Column()+1)
				if commentCell == nil {
					print.Panicf("分页[%s]表注释单元格是nil", sheet.Name)
					continue
				}
				s.Comment = commentCell.Value
				print.Debugf("分页[%s]在%+v找到表名[%s]，注释是[%s]", sheet.Name, s.TableNameOffset, s.Name, s.Comment)
			} else if s.AttributeBeginOffset == nil && isInList(cell.Value, attributeTags) {
				s.AttributeBeginOffset = NewOffset(row, column)
				print.Debugf("分页[%s]在%+v找到属性开始标志", sheet.Name, s.AttributeBeginOffset)
			} else if s.DataBeginOffset == nil && isInList(cell.Value, dataTags) {
				s.DataBeginOffset = NewOffset(row, column)
				print.Debugf("分页[%s]在%+v找到数据开始标志", sheet.Name, s.DataBeginOffset)
			}
			if s.TableNameOffset != nil && s.AttributeBeginOffset != nil && s.DataBeginOffset != nil {
				// 找到所有tag，立即跳出
				print.Debugf("分页[%s]找到所有tag，继续", sheet.Name)
				break scanTagLoop
			}
			column++
		}
		row++
	}

	if s.TableNameOffset == nil {
		// 没找到表名，不是静态表，跳过
		print.Debugf("分页[%s]没找到表名, 忽略", sheet.Name)
		return nil, nil
	}

	// 扫描全局字段
	if s.AttributeBeginOffset != nil {
		row = s.AttributeBeginOffset.Row()
		if s.DataBeginOffset != nil {
			maxRow = s.DataBeginOffset.Row()
		}
		for row < maxRow {
			nameCell := sheet.Cell(row, s.AttributeBeginOffset.Column()+1)
			if nameCell == nil {
				print.Panicf("分页[%s]属性[%d,%d]名字单元格是nil", sheet.Name, row, s.AttributeBeginOffset.Column()+1)
				continue
			}
			if nameCell.Value == "" {
				print.Debugf("分页[%s]属性[%d,%d]名字是空的", sheet.Name, row, s.AttributeBeginOffset.Column()+1)
				break
			}
			if nameCell.Value[0] == '#' {
				row++
				print.Debugf("分页[%s]属性[%d,%d]名字被注释掉", sheet.Name, row, s.AttributeBeginOffset.Column()+1)
				continue
			}

			typeCell := sheet.Cell(row, s.AttributeBeginOffset.Column()+2)
			if typeCell == nil {
				print.Panicf("分页[%s]属性[%d,%d]类型单元格是nil", sheet.Name, row, s.AttributeBeginOffset.Column()+2)
				continue
			}
			if typeCell.Value == "" {
				print.Debugf("分页[%s]属性[%d,%d]类型是空的", sheet.Name, row, s.AttributeBeginOffset.Column()+2)
				break
			}
			if typeCell.Value[0] == '#' {
				row++
				print.Debugf("分页[%s]属性[%d,%d]类型被注释掉", sheet.Name, row, s.AttributeBeginOffset.Column()+2)
				continue
			}

			valueCell := sheet.Cell(row, s.AttributeBeginOffset.Column()+3)
			if valueCell == nil {
				print.Panicf("分页[%s]属性[%d,%d]值单元格是nil", sheet.Name, row, s.AttributeBeginOffset.Column()+3)
				continue
			}
			if valueCell.Value == "" {
				row++
				print.Debugf("分页[%s]属性[%d,%d]值是空的", sheet.Name, row, s.AttributeBeginOffset.Column()+3)
				continue
			}
			if valueCell.Value[0] == '#' {
				row++
				print.Debugf("分页[%s]属性[%d,%d]值被注释掉", sheet.Name, row, s.AttributeBeginOffset.Column()+3)
				continue
			}

			commentCell := sheet.Cell(row, s.AttributeBeginOffset.Column()+4)
			if commentCell == nil {
				print.Panicf("分页[%s]属性[%d,%d]注释单元格是nil", sheet.Name, row, s.AttributeBeginOffset.Column()+3)
				continue
			}

			a, err := NewAttribute(nameCell.Value, typeCell.Value, valueCell.Value, commentCell.Value, row, s.AttributeBeginOffset.Column()+2)
			if err != nil {
				row++
				print.Debugf("分页[%s]new属性[%d,%d][%s]失败, %s", sheet.Name, row, s.AttributeBeginOffset.Column()+1, nameCell.Value, err)
				continue
			}
			s.Attributes = append(s.Attributes, a)
			row++

			print.Debugf("分页[%s]在[%d,%d]找到属性[%s]", sheet.Name, row, s.AttributeBeginOffset.Column()+1, nameCell.Value)
		}
	}

	var nameRow = s.DataBeginOffset.Row() + 2
	var commentRow = s.DataBeginOffset.Row() + 1
	var schemaRow = s.DataBeginOffset.Row() + 3

	for col := 0; col < maxCol; col++ {
		name := strings.TrimSpace(sheet.Cell(nameRow, col).Value)
		if name == "" {
			print.Debugf("分页[%s]第[%d]列字段的名字[%s]是空的，跳过", sheet.Name, col+1, name)
			continue
		}
		if name[0] == '#' {
			print.Debugf("分页[%s]第[%d]列字段的名字[%s]被注释掉，跳过", sheet.Name, col+1, name)
			continue
		}

		comment := strings.TrimSpace(sheet.Cell(commentRow, col).Value)
		if strings.ContainsAny(comment, "\n") {
			// 将注释中的换行替换成空格，避免生成代码失败
			comment = strings.ReplaceAll(comment, "\n", " ")
		}
		schemaString := strings.TrimSpace(sheet.Cell(schemaRow, col).Value)

		f := NewXlsxField(col, name, comment, schemaString)
		e := f.Format()
		if e != nil {
			switch e.(type) {
			case *ErrNotField:
				print.Debugf("分页[%s]第[%d]列[%s]不是字段，跳过", sheet.Name, col+1, name)
			case *ErrIgnoreField:
				print.Debugf("分页[%s]忽略第[%d]列字段[%s]", sheet.Name, col+1, name)
			default:
				print.Errorf("分页[%s]初始化第[%d]列字段[%s]失败，%s", sheet.Name, col+1, name, e)
			}
			continue
		}
		err = s.AppendXlsxField(f)
		if err != nil {
			err = fmt.Errorf("分页[%s]添加第[%d]列字段[%s]失败，%s", sheet.Name, col+1, name, err)
			return
		}
	}

	err = s.Format(g, clientMode)
	if err != nil {
		return
	}

	if readData {
		err = s.ReadData(sheet, g, clientMode)
		if err != nil {
			err = fmt.Errorf("分页[%s]读取数据失败，%s", sheet.Name, err)
			return
		}
	}

	return
}
